//
//  TempCacuExt.swift
//  ANOA
//
//  Created by 邱仙凯 on 2023/7/12.
//  Copyright © 2023 zwb. All rights reserved.
//

import UIKit

// MARK: 主表计算和细表计算   first 首次加载的标志
extension ConfigMenuForm {
    
    func computerAction(first:Bool = false,indexPath: IndexPath? = nil) {
        
        if indexPath.isSome {
            
            // 单条细表计算自己  多细表也只是计算自己 不管别的组
            computerDetailOne(group:self.cDIndex, indexx: indexPath!.section)
            
            
        } else {
            if rootTemp.multiDetailsParams.count > 0 {
                // 每一组都要算
                for y in 0..<self.rootTemp.multiDetailsParams.count {
                    
                    // 没传细表，计算所有细表，因为有些主表的变化需要重新计算细表
                    for i in 0..<self.detHandler[y].count {
                        computerDetailOne(group: y, indexx: i)
                    }
                    
                }
                
            } else {
                // 没传细表，计算所有细表，因为有些主表的变化需要重新计算细表
                for i in 0..<self.detHandler[0].count {
                    computerDetailOne(group: 0, indexx: i)
                }
            }
            
            
        }
        
        TempLog("\n\n\n【开始主表计算】--------------------")
        // 主表计算 主表要后算，因为需要用到细表的计算结果
        
        let tempMain = self.mainHandler.compactMap{$0.temp}.filter { $0.placeFlag == "1"}
        let tempComputerM = tempMain.filter { $0.computed_expression.unwrap != "" }
        for y in 0..<tempComputerM.count {
            let fNm = tempComputerM[y].field_nm.unwrap
            var comS = tempComputerM[y].computed_expression.unwrap
            TempLog("\(tempComputerM[y].field_annotation.unwrap) （\(tempComputerM[y].field_nm.unwrap)）触发计算---------")
            let detPa = containDDPa(condition: comS, rootTemp: rootTemp)
            if detPa != ""  {
                // 主表计算包含b.的都是细表累计，需统计细表的值,不会同时出现 a. b.
                var sumV:Double = 0
                var tempComS = ""
                
                var iddd = 0
                if let muindex = rootTemp.multiDetailsParams.getIndexFor({ onexx in
                    onexx == detPa
                }) {
                    iddd = muindex
                }
                
                
                for x in 0..<self.detHandler[iddd].count {
                    tempComS = comS
                    
                    
                    TempLog("细表公式：\(tempComS)")
                    // 给键排序，长的在前，防止 z_product 由于前面和 z_product_num 一样，优先替换了值
                    let detkeys = self.detHandler[iddd][x].dic.keys.sorted(by: { (obj1, obj2) -> Bool in
                        return obj1.count > obj2.count
                    })
                    for key in detkeys {
                        
                        tempComS = rpValue(exStr: tempComS,prefix: detPa, kkey: key, dic: self.detHandler[iddd][x].dic)
                        
                    }
                    
                    TempLog("带b表达式：\(tempComS)")
                    let resulttt = calculateHelper(tempComS)
                    TempLog("带b值 \(resulttt)")
                    
                    let finalV:Double = "\(resulttt)" == "nan" ? 0 : Double(resulttt).roundTo(2)
                    sumV = (sumV+finalV).roundTo(2)
                    TempLog("sumV\(sumV)")
                }
                TempLog("\(tempComputerM[y].field_annotation.unwrap) （\(tempComputerM[y].field_nm.unwrap)）汇总细表值最后结果\(sumV)\n\n\n\n")
                self.main[fNm] = sumV
                
            } else {
                
                TempLog("主表公式\(comS)")
                // 给键排序，长的在前，防止 z_product 由于前面和 z_product_num 一样，优先替换了值
                let mainkeys = self.main.keys.sorted(by: { (obj1, obj2) -> Bool in
                    return obj1.count > obj2.count
                })
                
                
                
                for key in mainkeys {
                    comS = rpValue(exStr: comS,prefix: "a", kkey: key, dic: self.main)
                    
                }
                TempLog("主表表达式：\(comS)")
                
                
                let resultX = comS2finalV(comS: comS)
                TempLog("\(tempComputerM[y].field_annotation.unwrap) （\(tempComputerM[y].field_nm.unwrap)）计算结果：\(resultX)\n")
                self.main[fNm] = resultX
            }
            
            
        }
        // 再次触发主表的影响  主要是有些值被计算后又有影响 ，不会影响效率，因为只有有变化才会触发
        self.setEffect(first)
        self.showMainData()
    }
    //  group:第几组（多细表的情况）  indexx : 第几条
    func computerDetailOne(group:Int,indexx:Int) {
        
        TempLog("\n\n【开始细表计算】-第\(group + 1)组--第\(indexx + 1)条-------")
        // 细表计算
        let tempComputerD = self.detHandler[group][indexx].temp.filter { $0.computed_expression.unwrap != "" }
        
        
        for y in 0..<tempComputerD.count {
            let currTempOne = tempComputerD[y]
            let fNm = currTempOne.field_nm.unwrap
            let fAno = currTempOne.field_annotation.unwrap
            var comS = currTempOne.computed_expression.unwrap
            
       
            
            TempLog("\n\(fAno)-(\(fNm)) 触发计算------------")
            TempLog("原始公式：\(comS)")
          
      
            // 先取本身，再取主表
            // 给键排序，长的在前，防止 z_product 由于前面和 z_product_num 一样，优先替换了值
            let detkeys = self.detHandler[group][indexx].dic.keys.sorted(by: { (obj1, obj2) -> Bool in
                return obj1.count > obj2.count
            })
            var prefix = "b"
            if self.rootTemp.multiDetailsParams.count > 0 {
                prefix = rootTemp.multiDetailsParams[group]
            }
            
            for key in detkeys {
                comS = rpValue(exStr: comS, prefix: prefix,kkey: key, dic: self.detHandler[group][indexx].dic)
            }
            
            // 给键排序，长的在前，防止 z_product 由于前面和 z_product_num 一样，优先替换了值
            let mainkeys = self.main.keys.sorted(by: { (obj1, obj2) -> Bool in
                return obj1.count > obj2.count
            })
            for key in mainkeys {
                comS = rpValue(exStr: comS,prefix: "a", kkey: key, dic: self.main)
            }
            TempLog("细表实际表达式：\(comS)")
            
            
            let countResult = comS2finalV(comS: comS)
            TempLog("计算结果：\(countResult)")
            
            
            
            let hasReg = currTempOne.grmmarArr.contains(GrammarType.setRoundDown.rawValue)
            if  hasReg {
                
                
                if let doubleOriV = Double(countResult) {
                    let cc = floor(doubleOriV).cleanZero
                    self.detHandler[group][indexx].dic[fNm] = "\(cc)"
                    TempLog("向下取整: \(countResult) -> \(cc)")
                }
            } else {
                self.detHandler[group][indexx].dic[fNm] = countResult
            }
            
            
            
        }
    }
    // 键  替换出真实 值  exStr ：表达式串  prefix:前缀     kkey：真实键值   dic：字典
    func rpValue(exStr:String,prefix:String,kkey:String,dic:[String:Any]) -> String {
        
        var newexStr = exStr
        let combineParam = "\(prefix).\(kkey)"
       
            
            let value = any2Str(dic[kkey])
            //          TempLog("value: \(value)")
            var vvv = ""
            if dateFromString(value).isSome {
                // 如果发现是日期  前后加 #  为了后续切成数组处理
                vvv = "#\(value)#"
            } else {
                vvv = value == "" ? "0" : value
            }
        if newexStr.contains(combineParam) {
            newexStr = newexStr.replacingOccurrences(of: combineParam, with: vvv)
        } else if newexStr.contains(kkey) {
            // 没前缀，默认当前，判断一下不是错误替换   比如：  a.number  b.number   没带前缀的number  如果写在
            //  细表，容易被 主表的数据替换掉，  判断前面是不是 没带点 才是真正的 无前缀
          // 排除一下前面有点的，才是真正的无前缀
            if !newexStr.contains(".\(kkey)") {
                newexStr = newexStr.replacingOccurrences(of: kkey, with: vvv)
            }
            
            
        }
        return newexStr
    }
    
//    func newRpValue(expresStr:String,mainDic:[String:Any],detailDics:[[String:Any]]) {
//        
//    }
//    
    
    // 从计算表达式 到 结果
    func comS2finalV(comS:String) -> String {
        var finalV = ""
        if comS.contains("#") {// 日期差   或者日期加上几天
            // #是日期，开始日期计算
            let cutArr = comS.components(separatedBy: "#").filter{ $0 != "" }
            TempLog(cutArr)
            
            // 计算日期差   2020-10-10  -  2020-09-10
            if cutArr.count == 3 , cutArr[1] == "-" {
                
                // 检测到日期格式 如：  2022-10-12
                if dateFromString(cutArr[0]).isSome && dateFromString(cutArr[2]).isSome {
                    let tmC = Date.timeComparison(aStr: cutArr[0], bStr: cutArr[2]).intWrap / 86400
                    finalV = "\(tmC)"
                } else {
                    finalV = "#"
                }
            } else if cutArr.count == 2 {
                
                if let dd1 = Date.change2Date(str: cutArr[0]) {
                    let xcresult = caculeTool(cutArr[1])
                    if xcresult == 0 {
                        // 处理另一个值为 0 的情况, 返回空
                        finalV = ""
                    } else {
                        let rer = Date.somedayPres(Int(-xcresult), date: cutArr[0])
                        finalV = rer
                    }
                    
                } else if let dd2 = Date.change2Date(str: cutArr[1]) {
                    let  xcresult = caculeTool(cutArr[0])
                    if xcresult == 0 {
                        finalV = ""
                    } else {
                        let rer = Date.somedayPres(Int(-xcresult), date: cutArr[1])
                        finalV = rer
                    }
                } else {
                    finalV = "#"
                }
                
            } else {
                 finalV = "#"
            }
            
        } else {
            // 把  -- 换成加号
            let finalComS = comS.replacingOccurrences(of: "--", with: "+")
            var resulttt:Double = 0.0
            if finalComS.contains("(") || finalComS.contains(")") {
                resulttt = Double(calculateHelper(finalComS))
            } else {
                // 暂时不支持带括号的
                
                resulttt = caculeTool(finalComS)
            }
            
            
            let rSt = String(resulttt)
            
            KSLog("计算结果--\(resulttt)")
            if rSt == "nan" || rSt == "inf" {
                finalV = ""
            } else {
                finalV = Double(rSt)!.roundTo(2).cleanZero
            }
            
        }
        return finalV
    }
}
